﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SGGWElevator
{
    /// <summary>
    /// Interaction logic for ElevatorInfoPanel.xaml
    /// Michał Szczepek
    /// </summary>
    public partial class ElevatorInfoPanel : UserControl
    {
        public ElevatorInfoPanel()
        {
            InitializeComponent();

            _floorLabels = new BiDictionary<Floor, string>();
            _floorLabels.Add(Floor.MinusOne, FloorNumbers.MinusOne);
            _floorLabels.Add(Floor.Lobby, FloorNumbers.Zero);
            _floorLabels.Add(Floor.One, FloorNumbers.One);
            _floorLabels.Add(Floor.Two, FloorNumbers.Two);
            _floorLabels.Add(Floor.Three, FloorNumbers.Three);

            SetFloor(Floor.MinusOne);
            SetDirection(Direction.Up);
        }

        /// <summary>
        /// Floor labels viewed next to the direction arrow.
        /// </summary>
        protected BiDictionary<Floor, string> _floorLabels;


        /// <summary>
        /// Currently displayed floor.
        /// </summary>
        protected Floor _actualFloor;

        /// <summary>
        /// Currently displayed floor.
        /// </summary>
        public Floor ActualFloor
        {
            get { return this._actualFloor; }
            set
            {
                // Check if changing is necessery.
                if (_actualFloor == value)
                    return;

                SetFloor(value);
            }
        }


        /// <summary>
        /// Current elevator movement direction.
        /// </summary>
        protected Direction _actualDirection;

        /// <summary>
        /// Current elevator movement direction.
        /// </summary>
        public Direction ActualDirection
        {
            get { return this._actualDirection; }
            set
            {
                // Check if changing is necessery.
                if (this._actualDirection != value)
                    SetDirection(value);
            }
        }


        /// <summary>
        /// Changes floor no metter if it's the same as previous one.
        /// </summary>
        /// <param name="floor">Floor to set</param>
        void SetFloor(Floor floor)
        {
            // Change floor
            _actualFloor = floor;

            // Change floor number
            FloorLabel.Content = _floorLabels.GetByFirst(floor);
        }


        /// <summary>
        /// Changes elevators movement direction no metter if it's the same as previous one.
        /// </summary>
        /// <param name="direction"></param>
        void SetDirection(Direction direction)
        {
            // Change direction (default: up)
            this._actualDirection = direction;

            // Change direction image
            string directionImagePath = string.Empty;

            switch (_actualDirection)
            {
                case Direction.Up:
                    directionImagePath = ImagesPaths.UpDirection;
                    break;
                case Direction.Down:
                    directionImagePath = ImagesPaths.DownDirection;
                    break;
                default:
                    goto case Direction.Up;
            }

            DirectionArrowImage.Source = new BitmapImage(
                new Uri(directionImagePath, UriKind.Relative));// TODO Implement dispatcher if necessery.
        }


        /// <summary>
        /// Reverses elevators movement direction
        /// </summary>
        public void ChangeDirection()
        {
            if (_actualDirection == Direction.Up)
                SetDirection(Direction.Down);
            else
                SetDirection(Direction.Up);
        }

        /// <summary>
        /// Increases floor by one.
        /// </summary>
        public void IncreaseFloor()
        {
            var nextFloor = _actualFloor.GetNext();
            ActualFloor = nextFloor;
        }


        /// <summary>
        /// Deacreses floor by one.
        /// </summary>
        public void DecreaseFloor()
        {
            var prevFloor = _actualFloor.GetPrevious();
            ActualFloor = prevFloor;
        }



        /// <summary>
        /// Paths to images.
        /// </summary>
        class ImagesPaths
        {
            public static readonly string UpDirection = @"/Images/ElevatorInfoPanel/up.png";
            public static readonly string DownDirection = @"/Images/ElevatorInfoPanel/down.png";
        }

        /// <summary>
        /// Floor numbers, can be used as labels.
        /// </summary>
        class FloorNumbers
        {
            public static readonly string MinusOne = "-1";
            public static readonly string Zero = "0";
            public static readonly string One = "1";
            public static readonly string Two = "2";
            public static readonly string Three = "3";
        }
    }
}
